package encome.work.utils;

import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;

import javax.websocket.RemoteEndpoint;
import javax.websocket.Session;
import java.io.IOException;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

@Slf4j
public class WebSocketUtil {

    // ========== 会话相关 ==========

    /**
     * Session 与用户的映射
     */
    private static final Map<String, Session> SESSION_USER_MAP = new ConcurrentHashMap<>();
    private static final Map<String, Session> SESSION_STAFF_MAP = new ConcurrentHashMap<>();
    private static final Map<String, Session> SESSION_ALL_MAP = new ConcurrentHashMap<>();

    public Set<String> getOnlineStaff() {
        return SESSION_STAFF_MAP.keySet();
    }

    public Set<String> getOnlineUser() {
        return SESSION_STAFF_MAP.keySet();
    }

    public static boolean isOnline(String id){
        return SESSION_ALL_MAP.containsKey(id);
    }
//    @Scheduled(fixedRate = 3000)
//    public static void heartCheck() {
//        for (Session session : SESSION_ALL_MAP.values()
//        ) {
//            sendTextMessage(session,"ping");
//        }
//    }

    /**
     * 添加 Session 。在这个方法中，会添加用户和 Session 之间的映射
     *
     * @param session Session
     */
    public static void addSession(String id, boolean isStaff, Session session) {
        if (isStaff) {
            SESSION_STAFF_MAP.put(id, session);
        } else {
            SESSION_USER_MAP.put(id, session);
        }
        SESSION_ALL_MAP.put(id,session);
    }

    /**
     * 移除 Session 。
     *
     * @param session Session
     */
    public static void removeSession(String id,Session session) {
        // 从 SESSION_USER_MAP 中移除
        if (SESSION_USER_MAP.containsKey(id))
            SESSION_USER_MAP.remove(id);
        if (SESSION_STAFF_MAP.containsKey(id))
            SESSION_STAFF_MAP.remove(id);
        if(SESSION_ALL_MAP.containsKey(id))
            SESSION_ALL_MAP.remove(id);
    }

    // ========== 消息相关 ==========

    /**
     * 广播发送消息给所有在线用户，不包括客服
     *
     * @param message 消息体
     */
    public static void broadcast(String message) {
        // 创建消息
//        String messageText = buildTextMessage(type, message);
        // 遍历 SESSION_USER_MAP ，进行逐个发送
        for (String id : SESSION_USER_MAP.keySet()) {
            sendTextMessage(SESSION_USER_MAP.get(id), message);
        }
    }

    public static void broadcastToOnlineStaff(String message) {
        // 创建消息
//        String messageText = buildTextMessage(type, message);
        // 遍历 SESSION_USER_MAP ，进行逐个发送
        for (String id : SESSION_STAFF_MAP.keySet()) {
            sendTextMessage(SESSION_STAFF_MAP.get(id), message);
        }
    }

    /**
     * 发送消息给单个人的 Session
     *
     * @param id
     * @param message 消息体
     */
    public static void sendTo(String id, String message) {
        Session session = null;
        if (SESSION_USER_MAP.containsKey(id))
            session = SESSION_USER_MAP.get(id);
            // 遍历给单个 Session ，进行逐个发送
        else if (SESSION_STAFF_MAP.containsKey(id))
            session = SESSION_STAFF_MAP.get(id);
        sendTextMessage(session, message);
    }

    public static void sendToOneStaff(String id, String message) {
        Session session = SESSION_STAFF_MAP.get(id);
        // 遍历给单个 Session ，进行逐个发送
        sendTextMessage(session, message);
    }

    public static long getOnlineUserCount() {
        return SESSION_USER_MAP.size();
    }

    public static long getOnlineStaffCount() {
        return SESSION_STAFF_MAP.size();
    }

    /**
     * 真正发送消息
     *
     * @param session     Session
     * @param messageText 消息
     */
    private static void sendTextMessage(Session session, String messageText) {
        //不在线的两种情况
        if (session == null) {
            return;
        }
        RemoteEndpoint.Basic basic = session.getBasicRemote();
        if (basic == null) {
            return;
        }
        try {
            basic.sendText(messageText);
        } catch (IOException e) {
            log.info("[sendTextMessage][session({}) 发送消息{}) 发生异常",
                    session, messageText, e);
        }
    }

}
